package com.ezlcp.commons.listener;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson2.JSON;
import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.ezlcp.commons.constant.StatusEnum;
import com.ezlcp.commons.dto.Datasource;
import com.ezlcp.commons.tool.StringUtils;
import com.ezlcp.commons.utils.DruidUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author Elwin ZHANG
 * @description: Nacos数据源更新项监听程序<br />
 * @date 2023/6/6 15:34
 */
@Component
@Slf4j
public class NacosDataSourceListener extends AbstractListener {

    /***
     *  上次刷新新时间
     */
    private static Date lastRefreshTime;

    /***
     *  上次取得的配置
     */
    private static String lastConfig;

    /***
     * 保存动态数据源的map
     */
    private static HashMap<String, DruidDataSource> dsMap = new HashMap<>();

    /***
     * @description 获取自定义的数据源
     * @param dsId 数据源Id
     * @return com.alibaba.druid.pool.DruidDataSource
     * @author Elwin ZHANG
     * @date 2023/6/8 17:32
     */
    public static DruidDataSource getDataSource(String dsId) {
        return dsMap.get(dsId);
    }

    /***
     * @description 更新数据源
     * @param isInit 是否初始化调用
     * @param dsInfo 数据源信息
     * @author Elwin ZHANG
     * @date 2023/6/7 9:56
     */
    public static void refreshDatasource(String dsInfo, boolean isInit) {
        //解析JSON
        List<Datasource> list = null;
        try {
            list = JSON.parseArray(dsInfo, Datasource.class);
        } catch (Exception e) {
            log.error("解析Nacos中配置的数据源JSON出错：" + e.getMessage(), e);
        }
        if (list == null || list.size() == 0) {
            return;
        }

        //循环处理自定义数据源记录
        for (var ds : list) {
            var updateTime = ds.getUpdateTime();
            //非初次刷新，且数据更新时间在上次刷新时间之前，则跳过
            if (!isInit && lastRefreshTime != null && updateTime != null && updateTime.before(lastRefreshTime)) {
                continue;
            }
            //删除数据源
            if (ds.getStatus() == StatusEnum.deleted.getValue()) {
                removeDataSource(ds.getDsId());
            } else {
                editDataSource(ds);
            }
        }
    }

    /***
     * @description 释放自定义的数据源
     * @param dsId 数据源ID
     * @author Elwin ZHANG
     * @date 2023/6/13 10:01
     */
    public static void removeDataSource(String dsId) {
        var dataSource = dsMap.get(dsId);
        if (dataSource == null) {
            return;
        }
        try {
            if (!dataSource.isClosed()) {
                dataSource.close();
            }
        } catch (Exception e) {
            log.info("释放数据源[ID:" + dsId + "]错误：" + e.getMessage());
        }
        dsMap.remove(dsId);
    }

    /***
     * @description 修改或新增数据源
     * @param datasource 数据源对象
     * @author Elwin ZHANG
     * @date 2023/6/7 10:37
     */
    private static void editDataSource(Datasource datasource) {
        String dsId = datasource.getDsId();
        //先删除旧的数据源，如果存在的话
        removeDataSource(dsId);
        //重新创建数据源
        var ds = DruidUtils.createDatasource(datasource);
        dsMap.put(dsId, ds);
    }

    /***
     * @description 配置项改变的回调
     * @param configInfo 新的配置值
     */
    @Override
    public void receiveConfigInfo(String configInfo) {
        //配置未变化，不用刷新
        if (StringUtils.isNotEmpty(configInfo) && configInfo.equals(lastConfig)) {
            return;
        }
        log.info("=====数据源配置更新为:" + configInfo);
        refreshDatasource(configInfo, false);
        lastConfig = configInfo;
        lastRefreshTime = new Date();
    }
}
